﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using MetadataBasedConfigArch.Framework;
using MetadataBasedConfigArch.Framework.Model;
using System.Data.Objects;
using MetadataBasedConfigArch.Framework.Entity;
using System.Xml;

namespace MetadataBasedConfigArch.Model
{
    public class DataEntityProvider:MetadataBasedConfigArch.Framework.IMetadataBasedEntityProvider
    {
        #region Ctors

        public DataEntityProvider(MDAEntities entitiesContext)
        {
            MDAEntities = entitiesContext;
            Initialize();
        }

        public DataEntityProvider(string entitiesCnnString)
        {
            MDAEntities = new MDAEntities(entitiesCnnString);
            Initialize();
        }

        #endregion

        #region Fields

        protected Dictionary<Type, Func<MDAEntities, object>> allEntities;

        #endregion

        #region Properties
                 
        public MDAEntities MDAEntities
        {
            get;
            protected set;
        }

        #endregion

        #region Implements Framework.IEntityProvider interface
         
        public IEnumerable<T> Load<T>()
        {
            IEnumerable<T> enumerable = allEntities[typeof(T)](MDAEntities) as IEnumerable<T>;
            return StaticConstraintHelper.IncludeStaticConstraint&&(typeof(IStaticConstrainable).IsAssignableFrom(typeof(T))) 
                ? enumerable.IncludeStaticConstraint() 
                : enumerable;
        }

        public IEnumerable<T> Load<T>(Func<T, bool> predicate)
        {
            IEnumerable<T> enumerable = allEntities[typeof(T)](MDAEntities) as IEnumerable<T>;
            return StaticConstraintHelper.IncludeStaticConstraint && (typeof(IStaticConstrainable).IsAssignableFrom(typeof(T)))
                ? enumerable.IncludeStaticConstraint().Where(predicate)
                : enumerable.Where(predicate);
        }
        
        public void Dispose()
        {
            MDAEntities.Dispose();
        }

        #endregion 
         

        public IConfigMeta GetConfigMeta(String configTypeName, String configMetaContent)
        { 
            return(from cm in MDAEntities.ConfigMetas.Include("ConfigType1")
                    where cm.ConfigType1.Name == configTypeName
                       && cm.Content == configMetaContent
                    select cm).FirstOrDefault();
        }

        public int Save()
        {
            return MDAEntities.SaveChanges();
        }

        public void Initialize()
        {
            allEntities = new Dictionary<Type, Func<MDAEntities, object>>();
            allEntities.Add(typeof(Model.ConfigMeta), m => m.ConfigMetas);
            allEntities.Add(typeof(Model.ConfigMetaConfigData), m => m.ConfigMetaConfigDatas);
            allEntities.Add(typeof(Model.ConfigMetaConfigInfo), m => m.ConfigMetaConfigInfoes);
            allEntities.Add(typeof(Model.ConfigMetaConfigInfoProperty), m => m.ConfigMetaConfigInfoProperties);
            allEntities.Add(typeof(Model.ConfigMetaRelation), m => m.ConfigMetaRelations);
            allEntities.Add(typeof(Model.ConfigMetaRelationType), m => m.ConfigMetaRelationTypes);
            allEntities.Add(typeof(Model.ConfigType), m => m.ConfigTypes);
            allEntities.Add(typeof(Model.Tenant), m => m.Tenants);

            allEntities.Add(typeof(Model.Page), m => m.Pages);
            allEntities.Add(typeof(Model.Document), m => m.Documents);
            allEntities.Add(typeof(Model.User), m => m.Users);

            allEntities.Add(typeof(IConfigMeta), m => m.ConfigMetas);
            allEntities.Add(typeof(IConfigMetaConfigData), m => m.ConfigMetaConfigDatas);
            allEntities.Add(typeof(IConfigMetaConfigInfo), m => m.ConfigMetaConfigInfoes);
            allEntities.Add(typeof(IConfigMetaConfigInfoProperty), m => m.ConfigMetaConfigInfoProperties);
            allEntities.Add(typeof(IConfigMetaRelation), m => m.ConfigMetaRelations);
            allEntities.Add(typeof(IConfigMetaRelationType), m => m.ConfigMetaRelationTypes);
            allEntities.Add(typeof(IConfigType), m => m.ConfigTypes);
            allEntities.Add(typeof(ITenant), m => m.Tenants);
        }
    }
}
